module Memory (Clock, A1, A2, RD1, RD2, WD1, WE);

	input	[31:0]		A1, A2, WD1;
	input					Clock, WE;
	output	[31:0]	RD1, RD2;
	
	reg		[31:0]		InstructionMem 	[1023:0];
	reg		[31:0]		DataHeapMem 		[1023:0];
	reg		[31:0]		DataStackMem 		[1023:0];
	reg		[31:0]		FrameBufMem			[262144:0];
	
	reg		[31:0]		RD1, RD2;
	
	reg		[1:0]		ReadType1, ReadType2;
	reg		[9:0]		ReadAddr1, ReadAddr2;
	
	localparam InstructionAddrTop	= 20'h00400;
	localparam DataHeapAddrTop 	= 20'h10010;
	localparam DataStackAddrTop	= 20'h7ffff;
	
	localparam NoSuchReadAddr		= 2'b00;
	localparam InstructionAddr		= 2'b01;
	localparam DataHeapAddr			= 2'b10;
	localparam DataStackAddr		= 2'b11;
	
	always @(posedge Clock) begin
		if (WE) begin
			case (A1[31:12])
				InstructionAddrTop:	InstructionMem[A1[11:2]]	<= WD1;
				DataHeapAddrTop: 		DataHeapMem[A1[11:2]]		<= WD1;
				DataStackAddrTop: 	DataStackMem[A1[11:2]]		<= WD1;
				default:			;
			endcase
		end
		
		ReadAddr1 <= A1[11:2];
		case (A1[31:12])
			InstructionAddrTop: 	ReadType1 <= InstructionAddr;
			DataHeapAddrTop:		ReadType1 <= DataHeapAddr;
			DataStackAddrTop: 	ReadType1 <= DataStackAddr;
			default:					ReadType1 <= NoSuchReadAddr;
		endcase
		
		ReadAddr2 <= A2[11:2];
		case (A2[31:12])
			InstructionAddrTop: 	ReadType2 <= InstructionAddr;
			DataHeapAddrTop:		ReadType2 <= DataHeapAddr;
			DataStackAddrTop: 	ReadType2 <= DataStackAddr;
			default:					ReadType2 <= NoSuchReadAddr;
		endcase
	end
	
	always @(*) begin
		case (ReadType1)
			InstructionAddr:	RD1 = InstructionMem[ReadAddr1];
			DataHeapAddr:		RD1 = DataHeapMem[ReadAddr1];
			DataStackAddr:		RD1 = DataStackMem[ReadAddr1];
			default:		RD1 = 32'bx;
		endcase
		
		case (ReadType2)
			InstructionAddr:	RD2 = InstructionMem[ReadAddr2];
			DataHeapAddr:		RD2 = DataHeapMem[ReadAddr2];
			DataStackAddr:		RD2 = DataStackMem[ReadAddr2];
			default:				RD2 = 32'bx;
		endcase
	end
	
endmodule
